﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
using VisionEstereo.SegmentacionColores;



namespace VisionEstereo
{
    public partial class ResultadosAlgoritmo
    {
        private System.Drawing.Bitmap disparidades, imagenFiltrada;
        private int disparidadMaxima;
        private int disparidadMedia;
        private int disparidad;
        private App.TipoAlgoritmo tipoAlgoritmo;
        private int ancho, alto;

        public ResultadosAlgoritmo()
        {
            this.InitializeComponent();
        }      
        public void setImagenResultado(BitmapSource resultado)
        {
            this.imgResultado.Source = resultado;
        }

        public void setTipoAlgoritmo(App.TipoAlgoritmo tipoAlgoritmo)
        {
            this.tipoAlgoritmo = tipoAlgoritmo;
        }

        public void setDisparidad(int disp)
        {
            this.disparidad = disp;
        }


        /// <summary>
        /// Este método almacena un Bitmap de disparidades, para
        /// poder visualizar los datos al hacer clic sobre cada píxel.
        /// </summary>
        /// <param name="disparidades">Matriz de disparidades</param>
        public void setImagenDisparidades(System.Drawing.Bitmap disparidades)
        {
            this.disparidades = disparidades;
        }
                
        private void setLabelCoordenadas(Point punto)
        {
            int x = (int)punto.X;
            int y = (int)punto.Y;
            this.labelCoordenadas.Content = String.Format("Coordenadas: X = {0} Y = {1}", x, y);
        }

        private void setLabelDisparidad(int disparidad)
        {
            this.labelDisparidad.Content = String.Format("Disparidad: {0}", disparidad);
        }

        public void setImagenInicial(System.Drawing.Bitmap bitmapIzquierda)
        {
            System.Windows.Media.Imaging.BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmapIzquierda.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
            this.imagenInicial.Source = bitmapSource;
        }


        public void setDisparidadesMaximaYMedia(int disparidadMaxima, int disparidadMedia)
        {
            this.disparidadMaxima = disparidadMaxima;
            this.disparidadMedia = disparidadMedia;
            labelDisparidad.Content = String.Format("Disparidad máxima: {0} Disparidad media: {1}", disparidadMaxima, disparidadMedia);
        }

        private void botonHome_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            PantallaInicial pagInicio = new PantallaInicial();
            this.NavigationService.Navigate(pagInicio);
        }

        private void imgResultado_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            setLabelCoordenadas(e.GetPosition(imgResultado));
        }

        public void setTamañoImagenReal(int x, int y)
        {
            ancho = x;
            alto = y;
        }


        private void imgResultado_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // En el anaglifo y la detección de objetos no debemos responder a los click  
            if (!tipoAlgoritmo.Equals(App.TipoAlgoritmo.Anaglifo) && !tipoAlgoritmo.Equals(App.TipoAlgoritmo.DeteccionObjetos))
            {                            
                int x = (int)e.GetPosition(imgResultado).X;
                int y = (int)e.GetPosition(imgResultado).Y;
               
                int with = (int)((x * ancho) / imgResultado.ActualWidth);
                int height = (int)((y * alto) / imgResultado.ActualHeight);

                int r = disparidades.GetPixel(with, height).R;
               
                setLabelDisparidad(r);
 
            }

        }       

        private void BotonGuardar_Click(object sender, RoutedEventArgs e)
        {
            SaveFileDialog dialogoGuardar = new SaveFileDialog();
            dialogoGuardar.Filter = "Archivos de imagen|*.jpg;*.png;*.bmp";
            dialogoGuardar.Title = "Elija dónde guardar su imagen";

            if (dialogoGuardar.ShowDialog() == DialogResult.OK && dialogoGuardar.FileName != "")
            {
                //guardamos bitMap
                BitmapSource bitmap = imgResultado.Source as BitmapSource;
                if (bitmap != null)
                {
                    JpegBitmapEncoder jpeg = new JpegBitmapEncoder();
                    jpeg.Frames.Add(BitmapFrame.Create(bitmap));
                    using (Stream stm = File.Create(dialogoGuardar.FileName))
                    {
                        jpeg.Save(stm);
                    }
                }
                //guardamos mapaDisparidad
                int dimx = (int)this.imgResultado.Source.Width;
                int dimy = (int)this.imgResultado.Source.Height;
                char[] myChar = { '.', 'j', 'p', 'g' };
                string nombreFich = dialogoGuardar.FileName.TrimEnd(myChar);
                StreamWriter fichero = new StreamWriter(nombreFich + "_mapaDisparidad.txt");

                for (int i = 0; i < dimx; i++)
                {
                    for (int j = 0; j < dimy; j++)
                    {
                        fichero.WriteLine(disparidades.GetPixel(i, j).R); //no se si esto esta bien, si asi se coge bien la dipsaridad                        
                    }
                }
                fichero.Close();
            }
        }


        int max(int a, int b) { if (a > b) return a; return b; }
        int min(int a, int b) { if (a < b) return a; return b; }

        private void BotonFiltro_Click(object sender, RoutedEventArgs e)
        {
            int dimx, dimy;
            int idx, ign;
            int i, j, k, l, m, cl, cu, rl, ru, mode;
            double[] pen;
            double penmax;

            ElegirFiltro ventanaFiltro = new ElegirFiltro();
            if (ventanaFiltro.ShowDialog() == true)
            {

                int tam = Int32.Parse(ventanaFiltro.tamVentanaBox.Text);

                dimx = (int)this.imgResultado.Source.Width;
                dimy = (int)this.imgResultado.Source.Height;


                int[,] matrizSalida = new int[dimx, dimy];
                int[] win = new int[2];


                pen = new double[256];

                ign = 0;
                win[0] = tam;
                win[1] = tam;

                for (i = 0; i < dimx; i++)        // for every pixel
                {
                    for (j = 0; j < dimy; j++)
                    {
                        for (m = 0; m < 256; m++) pen[m] = 0;  // zero out bins    //TODO:poner tam a nº de clases
                        mode = 0; penmax = 0;          // clear mode and max bin count

                        rl = max(0, i - win[0]);          // set up local windows
                        ru = min((int)dimx, i + win[0]);
                        cl = max(0, j - win[1]);
                        cu = min((int)dimy, j + win[1]);

                        for (k = rl; k < ru; k++)             // for every pixel in local window
                        {
                            for (l = cl; l < cu; l++)
                            {
                                idx = this.disparidades.GetPixel(k, l).R;  // get bin number

                                if (idx < ign) continue;      // assume bad pixels if below ign

                                pen[idx]++;                // increment bin count
                                if (pen[idx] > penmax)       // if its a new mode
                                {
                                    penmax = pen[idx];    // update bin count max
                                    mode = idx;            // update mode
                                }
                            }
                        }
                        matrizSalida[i, j] = mode;              // set output pixel to mode from window
                    }
                }
                //dibujar nueva matriz
                imagenFiltrada = new System.Drawing.Bitmap((int)this.imgResultado.Source.Width, (int)this.imgResultado.Source.Height);

                for (i = 0; i < dimx; i++)
                {
                    for (j = 0; j < dimy; j++)
                    {
                        int p = matrizSalida[i, j];
                        System.Drawing.Color color_aux = System.Drawing.Color.FromArgb(p, p, p);
                        imagenFiltrada.SetPixel(i, j, color_aux);
                    }
                }
                System.Drawing.Bitmap bmp = ProyectoSI.ColorMapDisparidades.ObtenerColorMap(imagenFiltrada, this.disparidad);

                //meter Bitmap a la imagen
                System.Windows.Media.Imaging.BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                setImagenResultado(bitmapSource);

            }
        }





        public void fueraFiltro()
        {
            this.BotonFiltro.IsEnabled = false;
        }

        public void fueraLabel()
        {
            this.labelDisparidad.IsEnabled = false;
        }
    }

       
	
}